package com.mmd.utils;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.servlet.http.HttpServletRequest;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;

import net.sf.json.JSONObject;

@SuppressWarnings({ "unchecked", "deprecation" })
public class HttpClient {
	//设置连接超时时间
	private static final int CONNECTION_TIMEOUT = 30*1000;
	private static final int SO_TIMEOUT = 30*1000;

	private org.apache.http.client.HttpClient client = null;

	public HttpClient() {
		init();
	}
	
	private void init() {
		try {
			HttpParams params = new BasicHttpParams();
			//设置请求超时10秒钟    
			params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, CONNECTION_TIMEOUT);
			//设置等待数据超时时间10秒钟  
			params.setParameter(CoreConnectionPNames.SO_TIMEOUT, SO_TIMEOUT);
			// 创建SSLContext对象，并使用我们指定的信任管理器初始化
			TrustManager[] tm = { new MyX509TrustManager() };
			SSLContext sslContext = SSLContext.getInstance("SSL");
			sslContext.init(null, tm, new java.security.SecureRandom());
			SSLSocketFactory socketFactory = new SSLSocketFactory(sslContext);
			socketFactory.setHostnameVerifier(new AllowAllHostnameVerifier());
			//设置访问协议   
		    SchemeRegistry schreg = new SchemeRegistry();    
		    schreg.register(new Scheme("http",80,PlainSocketFactory.getSocketFactory()));   
		    schreg.register(new Scheme("https", 443, socketFactory));
		    
		    PoolingClientConnectionManager pccm = new PoolingClientConnectionManager(schreg);  
		    pccm.setDefaultMaxPerRoute(1000); //每个主机的最大并行链接数    
		    pccm.setMaxTotal(10000);          //客户端总并行链接最大数     
			client = new DefaultHttpClient(pccm, params);

		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
	
	public  Map<String, Object> post(Map<String, String> map,String url,Logger logger) {
		List<NameValuePair> param = new ArrayList<NameValuePair>();
		for (String key : map.keySet()) {
			param.add(new BasicNameValuePair(key, map.get(key)));
		}
		if (url.endsWith("?")) {
			url = url.substring(0, url.length()-1);
		}
		HttpPost post = new HttpPost(url);
		try {
			post.setEntity(new UrlEncodedFormEntity(param, "UTF-8"));
			HttpResponse response = client.execute(post);
			logger.info("1.post 请求状态:{}",response.getStatusLine().getStatusCode());
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
				Map<String, Object> returnMap=new HashMap<String, Object>();
				logger.info("2.post 请求结果为：{}",jsonStr);
				returnMap = JSONObject.fromObject(jsonStr);
				return returnMap;
			}
		} catch (Exception e) {
			logger.info("post请求异常{}",e);
			e.printStackTrace();
		} 
		return null;
	}
	
	public  Map<String, Object> postQueryFXOrder(Map<String, String> map,String url,Logger logger) {
		List<NameValuePair> param = new ArrayList<NameValuePair>();
		for (String key : map.keySet()) {
			param.add(new BasicNameValuePair(key, map.get(key)));
		}
		if (url.endsWith("?")) {
			url = url.substring(0, url.length()-1);
		}
		HttpPost post = new HttpPost(url);
		try {
			post.setEntity(new UrlEncodedFormEntity(param, "UTF-8"));
			HttpResponse response = client.execute(post);
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
				logger.info("1.post 请求结果为：{}",jsonStr);
				Map<String, Object> returnMap=new HashMap<String, Object>();
				JSONArray array = JSON.parseArray(jsonStr);
				if (array.size() > 0){
					returnMap = (Map<String, Object>) array.get(0);
					return returnMap;
				}
			}
		} catch (Exception e) {
			logger.info("post请求异常{}",e);
			e.printStackTrace();
		} 
		return null;
	}
	
	public  Map<String, Object> get(String url) {
		HttpGet get = new HttpGet(url);
		try {
			HttpResponse response = client.execute(get);
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
				Map<String, Object> returnMap=new HashMap<String, Object>();
				returnMap = JSONObject.fromObject(jsonStr);
				return returnMap;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return null;
	}
	
	public  String postForXml(Map<String, String> map,String url,Logger logger) {
		List<NameValuePair> param = new ArrayList<NameValuePair>();
		for (String key : map.keySet()) {
			logger.info("输出key看看:{}，值：{}",key,map.get(key));
			param.add(new BasicNameValuePair(key, map.get(key)));
		}
		if (url.endsWith("?")) {
			url = url.substring(0, url.length()-1);
		}
		HttpPost post = new HttpPost(url);
		try {
			logger.info("请求参数param是：{}",param);
			post.setEntity(new UrlEncodedFormEntity(param, "UTF-8"));
			HttpResponse response = client.execute(post);
			logger.info("=========statusCode:{}",response.getStatusLine().getStatusCode());
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
				logger.info("返回的参数{}",jsonStr);
				return jsonStr;
			}
		} catch (Exception e) {
			logger.info("post请求异常{}",e);
			e.printStackTrace();
		} 
		return null;
	}
	
	/**
	 * 请求微信
	 * @param xmlStr
	 * @return
	 */
	public static String doPost(String data, String url, Logger logger) {
//		HttpPost post = new HttpPost(url);
//		try {
//			String str = new String(sendStr.getBytes(), "UTF-8");
//			StringEntity entity = new StringEntity(str);
//			post.setEntity(entity);
//			HttpResponse response = client.execute(post);
//			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
//				String returnXml = EntityUtils.toString(response.getEntity(), "UTF-8");
//				return returnXml;
//			}
//		} catch (Exception e) {
//			logger.info("请求微信异常：{}",e);
//			e.printStackTrace();
//		}
//		return "";
		
		CloseableHttpClient httpclient = null;
        try {
            logger.info("url:{}",url);
            logger.info("params:{}", data);
            httpclient = HttpClients.createDefault();
            HttpPost httpPost =new HttpPost(url);
            // 设置参数
            HttpEntity fe = new StringEntity(data,"UTF-8");
            httpPost.setEntity(fe);
            CloseableHttpResponse response = httpclient.execute(httpPost);
            try{
                try {
                    HttpEntity result = response.getEntity();
                    String str = EntityUtils.toString(result, "UTF-8");
                    logger.info("返回:{}",str);
                    return str;
                } catch (Exception e) {
                    logger.error("访问失败", e);
                }
            }finally {
                response.close();
            }
        }catch (Exception e2) {
            logger.error("请求失败",e2);
            e2.printStackTrace();
        } finally {
            try {
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
	}
	
	/** 
	* 获取用户真实IP地址，不使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址, 
	*  
	* 可是，如果通过了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP值，究竟哪个才是真正的用户端的真实IP呢？ 
	* 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。 
	*  
	* 如：X-Forwarded-For：192.168.1.110, 192.168.1.120, 192.168.1.130, 
	* 192.168.1.100 
	*  
	* 用户真实IP为： 192.168.1.110 
	*  
	* @param request 
	* @return 
	*/  
	public static String getIpAddress(HttpServletRequest request) {  
		String ip = request.getHeader("x-forwarded-for");  
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
			ip = request.getHeader("Proxy-Client-IP");  
		}  
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
			ip = request.getHeader("WL-Proxy-Client-IP");  
		}  
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
			ip = request.getHeader("HTTP_CLIENT_IP");  
		}  
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
			ip = request.getHeader("HTTP_X_FORWARDED_FOR");  
		}  
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
			ip = request.getRemoteAddr();  
		}  
		return ip;  
	} 
	
	public static String connectHttpsByPost(String url, File file) throws IOException{
		URL realUrl = new URL(url);
        // 打开和URL之间的连接
        URLConnection con = realUrl.openConnection();
        
		String result =null;
		con.setDoInput(true);

		con.setDoOutput(true);

		con.setUseCaches(false); // post方式不能使用缓存

		// 设置请求头信息

		con.setRequestProperty("Connection", "Keep-Alive");

		con.setRequestProperty("Charset", "UTF-8");
		// 设置边界

		String BOUNDARY = "----------" + System.currentTimeMillis();

		con.setRequestProperty("Content-Type",
				"multipart/form-data; boundary="

				+ BOUNDARY);

		// 请求正文信息

		// 第一部分：

		StringBuilder sb = new StringBuilder();

		sb.append("--"); // 必须多两道线

		sb.append(BOUNDARY);

		sb.append("\r\n");

		sb.append("Content-Disposition: form-data;name=\"media\";filelength=\""+file.length()+"\";filename=\""

				+ file.getName() + "\"\r\n");

		sb.append("Content-Type:application/octet-stream\r\n\r\n");

		byte[] head = sb.toString().getBytes("utf-8");

		// 获得输出流
		OutputStream outStream = con.getOutputStream();
		OutputStream out = new DataOutputStream(outStream);

		// 输出表头

		out.write(head);

		// 文件正文部分

		// 把文件已流文件的方式 推入到url中
		FileInputStream fileStream = new FileInputStream(file);
		DataInputStream in = new DataInputStream(fileStream);

		int bytes = 0;

		byte[] bufferOut = new byte[1024];

		while ((bytes = in.read(bufferOut)) != -1) {

			out.write(bufferOut, 0, bytes);

		}

		// 结尾部分

		byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");// 定义最后数据分隔线

		out.write(foot);

		out.flush();

		StringBuffer buffer = new StringBuffer();

		BufferedReader reader = null;

		try {

			// 定义BufferedReader输入流来读取URL的响应

			reader = new BufferedReader(new InputStreamReader(con.getInputStream()));

			String line = null;

			while ((line = reader.readLine()) != null) {

				buffer.append(line);

			}

			if (result == null) {

				result = buffer.toString();

			}

		} catch (IOException e) {

			System.out.println("发送POST请求出现异常！" + e);

			e.printStackTrace();

			throw new IOException("数据读取异常");

		} finally {

			if (reader != null) {

				reader.close();

			}
			if (out != null){
				out.close();
				out = null;
			}
			if (in != null){
				in.close();
				in = null;
			}
			if (outStream != null){
				outStream.close();
			}
			if (fileStream != null){
				fileStream.close();
			}
		}
		return result;
	}
}
